package cn.bugDance.infrastructure.aspect;

import cn.bugDance.infrastructure.annotation.CacheQuery;
import cn.bugDance.infrastructure.persistent.redis.IRedisService;
import cn.bugDance.types.enums.ResponseCode;
import cn.bugDance.types.exception.AppException;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.Method;

@Aspect
@Component
@Slf4j
public class CacheQueryAspect {

    @Resource
    private IRedisService redisService;

    @Pointcut("@annotation(cn.bugDance.infrastructure.annotation.CacheQuery)")
    public void pointCut(){}

    @Around("pointCut()")
    public Object cacheQuery(ProceedingJoinPoint jp){
        try{
            Object[] args = jp.getArgs();
            Class<?> clazz = jp.getTarget().getClass();
            Signature signature = jp.getSignature();
            MethodSignature methodSignature = (MethodSignature) signature;
            Method method = clazz.getDeclaredMethod(methodSignature.getName(), methodSignature.getParameterTypes());

            CacheQuery cacheQuery = method.getAnnotation(CacheQuery.class);

            String redisKey = cacheQuery.cacheKeyPrefix();
            if(args.length == 0){
                return jp.proceed();
            }
            int i = 0;
            for(; i < args.length - 1; i++){
                redisKey = redisKey.concat(String.valueOf(args[i]) + ":");
            }
            redisKey = redisKey.concat(String.valueOf(args[i]));
            Object result = redisService.getValue(redisKey);

            if(null == result){
                Object r = jp.proceed();
                redisService.setValue(redisKey, r);
                return jp.proceed();
            }
            return result;
        }catch (Exception e){
            log.info("【缓存自动化切面-基础层】: 参数配置错误, message: {}", e.getMessage());
            throw new AppException(ResponseCode.ILLEGAL_PARAMETER.getCode(), ResponseCode.ILLEGAL_PARAMETER.getInfo());
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    }
}
